using System;
using System.Collections.Generic;
using System.Text;
using GuavaData;
using System.Windows.Forms;
using System.ComponentModel;
using System.Data;

namespace GuavaLib
{
    public class GCheckedListBox : CheckedListBox, Guava
    {
        string gname;
        System.Windows.Forms.Label lab;
        DataView dv;
        Guid gid;

        public System.Windows.Forms.Label Label
        {
            get { return lab; }
            set { lab = value; }
        }

        #region Guava Members

        [Browsable(false)]
        public LaunchType LType
        {
            get { return LaunchType.NA; }
        }

        [Browsable(false)]
        public ControlType CType
        {
            get { return ControlType.Entity; }
        }

        [Browsable(false)]
        public string GText
        {
            get
            {
                if (this.lab == null) return null;
                return this.lab.Name;
            }
        }

        public string GName
        {
            get
            {
                if (gname == null) return this.Name;
                return gname;
            }
            set
            {
                gname = value;
            }
        }

        [Browsable(false)]
        public System.Drawing.Point GLocation
        {
            get { return this.GLocation; }
        }

        [Browsable(false)]
        public System.Drawing.Size GSize
        {
            get { return this.Size; }
        }

        [Browsable(false)]
        public List<Guava> GComponents
        {
            get
            {
                List<Guava> lg = new List<Guava>();

                // Make an extra column to hold the actual values
                List<string> ls = new List<string>();
                foreach (object o in this.Items) ls.Add(o.ToString());
                GEmpty ge = new GEmpty("Value", new GuavaData.Domain.Enumerated(ls.ToArray()));
                lg.Add(ge);
                return lg;
            }
        }

        public void GBind(string table, int i)
        {
            DataRow dr = AppData.ds.Tables[table].Rows[i];
            gid = (Guid)dr["id"];

            // Find parent and attach persistence handler
            Control p = this.Parent;
            while (!(p is GuavaForm))
            {
                if (p == null) return;
                if (!(p is Guava)) return;
                p = p.Parent;
            }
            GuavaForm gf = p as GuavaForm;
            gf.PersistSignal += new GuavaData.SignalToPersist(gf_PersistSignal);

            // Create a view of the destination table that only has the current ID's
            AppData.FetchRowsByFK(this.GName, gid);
            dv = (new DataView(AppData.ds.Tables[this.GName], "fk='" + gid.ToString() + "'", null, DataViewRowState.CurrentRows));
            dv.AllowNew = true;
            dv.AllowDelete = true;

            // Loop through rows in the table and check the items that need checking (sync state)
            for (int iList = 0; iList < this.Items.Count; iList++)
                this.SetItemChecked(iList, false);
            foreach (DataRowView drv in this.dv)
            {
                int iTemp = this.Items.IndexOf(drv["Value"].ToString());
                if (iTemp >= 0) this.SetItemChecked(iTemp, true);
            }
        }

        [Browsable(false)]
        public string GDefault
        {
            get { return null; }
        }

        [Browsable(false)]
        public string GToolTip
        {
            get
            {
                Control p = this.TopLevelControl;
                if (!(p is Guava)) return null;
                ToolTip t = (p as GuavaForm).GToolTipProvider;
                if (t == null) return null;

                // Fetch the tooltip and return it
                return t.GetToolTip(this);
            }
        }

        [Browsable(false)]
        public GuavaData.Domain.Domain GDomain
        {
            get { return new GuavaData.Domain.UniqueIdentifier(); }
        }

        public Guava this[string s]
        {
            get
            {
                foreach (Guava g in this.GComponents) if (g.GName == s) return g;
                return null;
            }
        }

        #endregion

        void gf_PersistSignal(object sender, PersistSignalEventArgs e)
        {
            if (e.bPersist) PersistChanges();
            else dv.Table.RejectChanges();
        }

        private void PersistChanges()
        {
            // Purge deleted rows
            dv.RowStateFilter = DataViewRowState.Deleted;
            foreach (DataRowView drv in dv)
                AppData.DeleteRow(dv.Table.TableName, (Guid)drv["id"]);

            // Add new rows
            dv.RowStateFilter = DataViewRowState.Added;
            foreach (DataRowView drv in dv)
                AppData.CommitRow(dv.Table.TableName, (Guid)drv["id"], DMLType.INSERT);

            // Finish
            dv.RowStateFilter = DataViewRowState.CurrentRows;
            dv.Table.AcceptChanges();
        }

        protected override void OnItemCheck(ItemCheckEventArgs ice)
        {
            base.OnItemCheck(ice);

            // ToDo: Add/Delete row as necessary
            string sTemp = this.Items[ice.Index].ToString();

            if (ice.NewValue == CheckState.Checked)
            {
                // Create a new row
                DataRowView drv = dv.AddNew();
                drv["id"] = Guid.NewGuid();
                drv["fk"] = this.gid;
                drv["Value"] = sTemp;
            }
            else
            {
                // Delete an existing row
                for (int i = 0; i < dv.Count; i++)
                {
                    if (dv[i]["Value"].Equals(sTemp))
                    {
                        dv.Delete(i);
                        return;
                    }
                }
            }
        }
    }
}
